# 史上最简单的 GUI (图形界面) 开发工具 - 快手 (PySimpleGUI 汉化版)
# 闲话少说, 直接上代码和例程, 一目了然, 见名知意

#%%
# 仅仅 39 行代码即可展示图形界面的绝大部分元素

导入 快手

快手.更改外观('青褐色')      

菜单定义 = [ ['文件', ['打开', '保存', '退出', '属性']],      
            ['编辑', ['粘贴', ['特殊', '常规'], '撤消']],      
            ['帮助', '关于...'] ]

列1 = [ [快手.标签('列 1', 背景颜色='#F7F3EC', 对齐='居中', 大小=(10, 1))],      
        [快手.旋钮控件(值选项=('旋钮控件 1', '2', '3'), 初始值='旋钮控件 1')],      
        [快手.旋钮控件(值选项=('旋钮控件 1', '2', '3'), 初始值='旋钮控件 2')],      
        [快手.旋钮控件(值选项=('旋钮控件 1', '2', '3'), 初始值='旋钮控件 3')] ]      

布局 = [      
    [快手.菜单(菜单定义)],      
    [快手.标签('一个窗口显示几乎所有图形部件!', 大小=(35, 1), 对齐='居中', 字体=("微软雅黑", 25), 边框样式=快手.山脊C)],    
    [快手.标签('这是一些文字...... 以及输入文字的地方')],      
    [快手.输入框('这是我输入的文字')],      
    [快手.框架(布局=[      
        [快手.复选框('复选框', 大小=(15,1)),  快手.复选框('第二个复选框!', 默认值=真)],      
        [快手.单选按钮('我的第一个单选按钮!', "单选按钮1", 默认值=真, 大小=(15,1)), 快手.单选按钮('我的第二个单选按钮!', "单选按钮1")]],
        标题='选项', 标题颜色='red', 边框样式=快手.凹陷C, 提示='用于设置标志')],      
    [快手.多行文本框(默认文本='这是默认文本, 如果您决定不键入任何东西', 大小=(35, 3)),      
        快手.多行文本框(默认文本='第二个多行文本框', 大小=(35, 3))],      
    [快手.组合框(('组合框 1', '组合框 2'), 大小=(20, 1)),      
        快手.滑块(范围=(1, 100), 方向='水平', 大小=(34, 20), 默认值=85)],      
    [快手.选项菜单(('菜单选项 1', '菜单选项 2', '菜单选项 3'), 大小=(10, 1))],      
    [快手.列表框(值选项=('列表框 1', '列表框 2', '列表框 3'), 大小=(30, 3)),      
        快手.框架('带标签组',[
            [快手.滑块(范围=(1, 100), 方向='垂直', 大小=(5, 20), 默认值=25),      
            快手.滑块(范围=(1, 100), 方向='垂直', 大小=(5, 20), 默认值=75),      
            快手.滑块(范围=(1, 100), 方向='垂直', 大小=(5, 20), 默认值=10),      
            快手.列(列1, 背景颜色='#F7F3EC')] ])],      
    [快手.标签('_'  * 100)],      
    [快手.标签('选择文件夹', 大小=(35, 1))],      
    [快手.标签('您的文件夹', 大小=(15, 1), 大小适应文本=假, 对齐='右'),      
        快手.输入框('默认文件夹'), 快手.文件夹浏览按钮()],      
    [快手.提交按钮(提示='点击提交此窗口'), 快手.取消按钮()]    
]      


窗口 = 快手.窗口类('图形界面元素', 布局, 默认元素大小=(40, 1), 任意地方抓取=假)      

事件, 值 = 窗口.读取()      

窗口.关闭()    

快手.弹窗('标题', '窗口结果', '点击的按钮是 "{}"'.格式化(事件), '值为:', 值)      

# %%
# 示例 1A - 最简单的一次性窗口
导入 快手

布局 = [ [快手.标签('我的一次性窗口')],      
         [快手.输入框()],      
         [快手.提交按钮(), 快手.取消按钮()] ]      

窗口 = 快手.窗口类('窗口标题', 布局)    

事件, 值 = 窗口.读取()    
窗口.关闭()

输入文本 = 值[0]    
快手.弹窗('您输入的文字: ', 输入文本)

# %%
导入 快手

布局 = [ [快手.标签('我的一次性窗口')],      
         [快手.输入框(键='-输入-')],           # 使用自定义键, 而非自动生成的键, 方便查找/引用窗口元素
         [快手.提交按钮(), 快手.取消按钮()] ]      

窗口 = 快手.窗口类('窗口标题', 布局)    

事件, 值 = 窗口.读取()    
窗口.关闭()

输入文本 = 值['-输入-']                       # 通过自定义键获取值
快手.弹窗('您输入的文字: ', 输入文本)

# %%
# 示例 2A - 持续存在的窗口, 使用事件循环实现多次读取
导入 快手    

快手.主题('深琥珀色')

布局 = [  [快手.标签('持续存在的窗口')],      
          [快手.输入框(键='-输入-')],      
          [快手.按钮('读取'), 快手.退出按钮()]  ]      

窗口 = 快手.窗口类('一直打开的窗口', 布局)      

只要 真:                             # 事件循环
    事件, 值 = 窗口.读取() 
    打印(事件, 值)       
    如果 事件 == 空 或 事件 == '退出':  # 退出窗口事件
        跳出      

窗口.关闭()

# %%
# 示例 2B - 持续存在的窗口, 使用事件循环实现多次读取, 而且更新窗口
导入 快手    

快手.主题('深蓝2')

布局 = [  [快手.标签('您键入的字符显示在这里:'), 快手.标签(大小=(15,1), 键='-输出-')],      
          [快手.输入框(键='-输入-')],      
          [快手.按钮('显示'), 快手.退出按钮(提示='退出窗口')]  ]      # 设置元素的提示

窗口 = 快手.窗口类('显示输入内容', 布局)

只要 真:                             # 事件循环
    事件, 值 = 窗口.读取() 
    窗口['显示'].设置提示('显示您输入的内容')   # 设置元素提示的另一种方法, 但不推荐
    打印(事件, 值)       
    如果 事件 == 空 或 事件 == '退出':  # 退出窗口事件
        跳出
    如果 事件 == '显示':
        窗口['-输出-'].更新(值['-输入-'])  # 将输出标签元素的内容更新为输入的内容; 注意查找元素的方法

窗口.关闭()  # 这一步不能忘

# %%
# 编程惯例
#    1. 导入 快手
#    2. 以  窗口[键]  的形式查找元素
#    3. 键为字符串时, 以如下方式命名: -键名-

# %%
导入 快手

快手.预览所有主题()

# %%
# 主题浏览器
导入 快手

快手.主题('深棕')


布局 = [[快手.标签('主题浏览器')],
          [快手.标签('点击一个主题, 查看演示窗口')],
          [快手.列表框(值选项=快手.主题列表(), 大小=(20, 12), 键='-列表-', 启用事件=真)],
          [快手.按钮('退出')]]

窗口 = 快手.窗口类('主题浏览器', 布局)

只要 真:  # 事件循环
    事件, 值 = 窗口.读取()
    如果 事件 在 (空, '退出'):
        跳出
    快手.主题(值['-列表-'][0])
    快手.弹窗_获取文本('这是 {} 外观'.格式化(值['-列表-'][0]))

窗口.关闭()

# %%
# 创建无标题栏和半透明窗口

导入 快手

布局 = [  [快手.标签('无边框且半透明的窗口')],
          [快手.按钮('❎', 按钮颜色=('#FF0000', '#000000'), 边框宽度=0, 键='退出')]  ]

窗口 = 快手.窗口类('窗口标题', 布局, 无标题栏=真, 阿尔法通道=0.5)

只要 真:  # 事件循环
    事件, 值 = 窗口.读取()
    # 打印(事件, 值)
    如果 事件 在 (空, '退出'):
        跳出
窗口.关闭()

# %%
# 进一步了解窗口元素的 '键'

导入 快手

快手.主题('沙滩')      

# 使用自动编号的键返回值

布局 = [
    [快手.标签('请输入您的个人信息')],
    [快手.标签('姓名', 大小=(15, 1)), 快手.输入框()],
    [快手.标签('地址', 大小=(15, 1)), 快手.输入框()],
    [快手.标签('电话', 大小=(15, 1)), 快手.输入框()],
    [快手.提交按钮(), 快手.取消按钮()]
]

窗口 = 快手.窗口类('简单的数据输入窗口', 布局)
事件, 值 = 窗口.读取()
窗口.关闭()
打印(事件, 值[0], 值[1], 值[2])    # 数据自动编号, 看起来像列表, 实则是字典形式

# %%
# 强大的预置弹窗功能
# 在脚本前端添加 GUI

导入 快手
# 导入 系统

# 文件名 = 系统.参数列表[1] 如果 长(系统.参数列表) > 1 否则 快手.弹窗_获取文件('要打开的文件')
文件名 = 快手.弹窗_获取文件('要打开的文件')

如果 非 文件名:
    快手.弹窗("取消", "未提供文件名")
    # 报 系统退出类("正在取消: 未提供文件名")
否则:
    快手.弹窗('您选择的文件是', 文件名)

# %%
# 高响应性输入

导入 快手

选项 = ('红色', '绿色', '蓝色', '黄色', '橙色', '紫色', '绿色')

布局 = [  [快手.标签('你最喜欢什么颜色?')],
          [快手.列表框(选项, 大小=(15, 长(选项)), 键='-颜色-', 启用事件=真)] ]  # 启用事件

窗口 = 快手.窗口类('挑选一个颜色', 布局)

只要 真:                  
    事件, 值 = 窗口.读取()
    如果 事件 == 空:
        跳出
    如果 值['-颜色-']:    # 如果列表中有项目被高亮显示
        快手.弹窗("你最喜欢的颜色是 {值['-颜色-'][0]}")
窗口.关闭()

# %%
# 输入验证

导入 快手

布局 = [  [快手.标签('只能输入数字')],
          [快手.输入框(键='-输入-', 启用事件=真)],
          [快手.按钮('退出')]  ]

窗口 = 快手.窗口类('数字输入验证', 布局)

只要 真:                  
    事件, 值 = 窗口.读取()
    如果 事件 在 (空, '退出'):
        跳出
    # 如果输入元素中的最后一个字符无效, 则将其删除
    如果 事件 == '-输入-' 且 值['-输入-'] 且 值['-输入-'][-1] 不在 ('0123456789.-'):
        窗口['-输入-'].更新(值['-输入-'][:-1])
窗口.关闭()

# %%
# 打印到输出框

导入 快手

布局 = [  [快手.标签('你打印输出的内容将显示在下面:')],
          [快手.输出框(大小=(50,10), 键='-输出-')],      # 输出框接管标准输出
          [快手.输入框(键='-输入-', 大小=(52,1))],
          [快手.按钮('走你'), 快手.按钮('清空'), 快手.按钮('退出')]  ]

窗口 = 快手.窗口类('窗口标题', 布局)

只要 真:                  
    事件, 值 = 窗口.读取()
    打印(事件, 值)
    如果 事件 在 (空, '退出'):
        跳出
    如果 事件 == '清空':
        窗口['-输出-'].更新('')
窗口.关闭()

# %%
# 保存和加载程序设置

导入 快手
从 jsonc 导入 加载, 转储
从 操作系统 导入 路径

配置文件C = 路径.连接(路径.目录名称(__文件__), r'配置文件.cfg')
默认配置C = {'最大用户数': 10, '用户数据文件夹': 空 , '主题': 快手.主题(), '邮编' : '100001'}
# 配置字典键映射到窗口元素键
配置键_元素键C = {'最大用户数': '-最大用户数-', '用户数据文件夹': '-用户文件夹-' , '主题': '-主题-', '邮编' : '-邮编-'}

##################### 加载/保存配置文件 #####################
函 加载配置(配置文件, 默认配置):
    试:
        管 打开(配置文件, 'r') 为 文:
            配置 = 加载(文)
    捕 异常类 为 异:
        快手.快速消息弹窗(f'异常 {异}', '未找到配置文件... 这就为你创建', 保持置顶=真, 背景颜色='#FF0000', 文本颜色='#FFFFFF')
        配置 = 默认配置
        保存配置(配置文件, 配置, 空)
    返回 配置


函 保存配置(配置文件, 配置, 值):
    如果 值:      # 如果另一窗口指定了一些值, 则填充这些值
        取 键 于 配置键_元素键C:  # 用从文件读取的值更新窗口
            试:
                配置[键] = 值[配置键_元素键C[键]]
            捕 异常类 为 异:
                打印(f'从窗口值更新配置出问题. 键 = {键}')

    管 打开(配置文件, 'w') 为 文:
        转储(配置, 文)

    快手.弹窗('配置已保存')

##################### 生成配置窗口 #####################
函 创建配置窗口(配置):
    快手.主题(配置['主题'])

    函 文字标签(文字): 返回 快手.标签(文字+':', 对齐='右', 大小=(15,1))

    布局 = [  [快手.标签('配置', 字体='Any 15')],
              [文字标签('最大用户数'), 快手.输入框(键='-最大用户数-')],
              [文字标签('用户文件夹'), 快手.输入框(键='-用户文件夹-'), 快手.文件夹浏览按钮(目标='-用户文件夹-')],
              [文字标签('邮编'), 快手.输入框(键='-邮编-')],
              [文字标签('主题'), 快手.组合框(快手.主题列表(), 大小=(20, 20), 键='-主题-')],
              [快手.按钮('保存'), 快手.按钮('退出')]  ]

    窗口 = 快手.窗口类('配置', 布局, 保持置顶=真, 定型=真)

    取 键 于 配置键_元素键C:   # 更新 窗口 管 the 值 读取 from 配置 file
        试:
            窗口[配置键_元素键C[键]].更新(值=配置[键])
        捕 异常类 为 异:
            打印(f'从配置更新快手窗口出问题. 键 = {键}')

    返回 窗口

##################### 程序主窗口和事件循环 #####################
函 创建主窗口(配置):
    快手.主题(配置['主题'])

    布局 = [  [快手.标签('这是主应用程序')],
              [快手.标签('这里添加窗口主要内容')],
              [快手.按钮('确定'), 快手.按钮('退出'), 快手.按钮('更改配置')]  ]

    返回 快手.窗口类('主应用程序', 布局)


函 主函数():
    窗口, 配置 = 空, 加载配置(配置文件C, 默认配置C)

    只要 真:             # 事件循环
        如果 窗口 是 空:
            窗口 = 创建主窗口(配置)

        事件, 值 = 窗口.读取()
        如果 事件 在 (空, '退出'):
            跳出
        如果 事件 == '更改配置':
            事件, 值 = 创建配置窗口(配置).读取(关闭=真)
            如果 事件 == '保存':
                窗口.关闭()
                窗口 = 空
                保存配置(配置文件C, 配置, 值)
    窗口.关闭()

主函数()

# %%
# 有时候需要通过浏览方式获取两个文件名, 然后进行比较.
# 使用输入框元素和浏览按钮可以实现: 既可以在输入框中输入文件名, 也可以点击浏览按钮来获取文件名.
导入 快手

快手.主题('淡蓝2')

布局 = [[快手.标签('输入两个文件进行比较')],
          [快手.标签('文件 1', 大小=(8, 1)), 快手.输入框(), 快手.文件浏览按钮()],
          [快手.标签('文件 2', 大小=(8, 1)), 快手.输入框(), 快手.文件浏览按钮()],
          [快手.提交按钮(), 快手.取消按钮()]]

窗口 = 快手.窗口类('文件比较', 布局)

事件, 值 = 窗口.读取()
窗口.关闭()
打印(f'您点击了 {事件}')
打印(f'您选择了文件 {值[0]} 和 {值[1]}')

# %%
# 长时操作与多线程
# 简单粗暴的长时操作

导入 快手
导入 时间

函 长时函数():
    时间.睡眠(10)

布局 = [[快手.输出框(大小=(60,10))],
          [快手.按钮('走你'), 快手.按钮('无'), 快手.按钮('退出')]  ]

窗口 = 快手.窗口类('嘿嘿', 布局)

只要 真:             # 事件循环
    事件, 值 = 窗口.读取()
    如果 事件 == 空 或 事件 == '退出':
        跳出
    如果 事件 == '走你':
        打印('就要调用长时函数啦')
        长时函数()
        打印('长时函数执行完毕')
窗口.关闭()

# 运行上面的程序时, 如果鼠标不碰任何东西, 它会安静地运行完毕; 
# 如果与该窗口交互, 例如点击 "无" 按钮, 很可能会得到 "窗口" 停止响应的系统提示.

# %%
# 长时操作与多线程
# 线程化长时操作, 解决 "无响应" 问题

导入 快手
导入 时间
导入 线程化

函 长时函数_线程(窗口):
    时间.睡眠(10)
    窗口.写入事件值('-线程完毕', '')    # 这个函数很有用

函 长时函数():
    线程化.线程类(目标=长时函数_线程, 参数=(窗口,), 守护=真).开始()

布局 = [[快手.输出框(大小=(60,10))],
          [快手.按钮('走你'), 快手.按钮('无'), 快手.按钮('退出')]  ]

窗口 = 快手.窗口类('嘿嘿', 布局)

只要 真:             # 事件循环
    事件, 值 = 窗口.读取()
    如果 事件 == 空 或 事件 == '退出':
        跳出
    如果 事件 == '走你':
        打印('就要调用长时函数啦')
        长时函数()
        打印('长时函数已启动')
    或如 事件 == '-线程完毕-':
        打印('长时函数执行完毕')
    否则:
        打印(事件, 值)
窗口.关闭()

# %%
# 长时操作与多线程
# 有反馈的长时操作

导入 快手
导入 时间
导入 线程化

函 长时函数_线程(窗口):
    取 i 于 范围(10):
        时间.睡眠(1)
        窗口.写入事件值('-线程进度', i) # *写入事件值* 函数可以随时使用, 这里用于显示进度
    窗口.写入事件值('-线程完毕', '')    

函 长时函数():
    线程化.线程类(目标=长时函数_线程, 参数=(窗口,), 守护=真).开始()

布局 = [[快手.输出框(大小=(60,10))],
          [快手.按钮('走你'), 快手.按钮('无'), 快手.按钮('退出')]  ]

窗口 = 快手.窗口类('嘿嘿', 布局)

只要 真:             # 事件循环
    事件, 值 = 窗口.读取()
    如果 事件 == 空 或 事件 == '退出':
        跳出
    如果 事件 == '走你':
        打印('就要调用长时函数啦')
        长时函数()
        打印('长时函数已启动')
    或如 事件 == '-线程完毕-':
        打印('长时函数执行完毕')
    否则:
        打印(事件, 值)
窗口.关闭()


# %%
# *钉子* 函数, 用于隐藏/显示部分区域

导入 快手

正三角 =  '▲'
倒三角 =  '▼'


函 收缩(布局, 键):
    """
    帮助函数, 创建一个可隐藏的列, 展现出收缩效果
    """
    返回 快手.钉子(快手.列(布局, 键=键))


第一区 = [  [快手.输入框('输入区 1', 键='-IN1-')],
            [快手.输入框(键='-IN11-')],
            [快手.按钮('按钮11', 按钮颜色=('#FFFF00', '#008000')), #黄色, 绿色
             快手.按钮('按钮12', 按钮颜色=('#FFFF00', '#008000')),
             快手.按钮('按钮13', 按钮颜色=('#FFFF00', '#008000'))]  ]

第二区 = [  [快手.输入框('输入区 2', 键='-IN2-')],
            [快手.输入框(键='-IN21-')],
            [快手.按钮('按钮21', 按钮颜色=('#FFFF00', '#800080')), #黄色, 紫色
             快手.按钮('按钮22', 按钮颜色=('#FFFF00', '#800080')),
             快手.按钮('按钮23', 按钮颜色=('#FFFF00', '#800080'))]  ]


布局 =   [  [快手.标签('有两个可隐藏部分的窗口')],
            [快手.复选框('空白复选框'), 快手.复选框('隐藏第二区', 启用事件=真, 键='-显示第二区-复选框')],
            #### 第一区 ####
            [快手.标签(倒三角, 启用事件=真, 键='-显示第一区-', 文本颜色='#FFFF00'), 快手.标签('第一区', 启用事件=真, 文本颜色='#FFFF00', 键='-显示第一区-标签')],
            [收缩(第一区, '-第一区-')],
            #### 第二区 ####
            [快手.标签(倒三角, 启用事件=真, 键='-显示第二区-', 文本颜色='#800080'),
             快手.标签('第二区', 启用事件=真, 文本颜色='#800080', 键='-显示第二区-标签')],
            [收缩(第二区, '-第二区-')],
            #### 底部按钮 ####
            [快手.按钮('按钮A'), 快手.按钮('按钮B'), 快手.按钮('退出')]  ]

窗口 = 快手.窗口类('可见/不可见元素演示', 布局)

已显示1, 已显示2 = 真, 真

只要 真:             
    事件, 值 = 窗口.读取()
    打印(事件, 值)
    如果 事件 == 空 或 事件 == '退出':
        跳出

    如果 事件.开头是('-显示第一区-'):
        已显示1 = 非 已显示1
        窗口['-显示第一区-'].更新(倒三角 如果 已显示1 否则 正三角)
        窗口['-第一区-'].更新(可见=已显示1)

    如果 事件.开头是('-显示第二区-'):
        已显示2 = 非 已显示2
        窗口['-显示第二区-'].更新(倒三角 如果 已显示2 否则 正三角)
        窗口['-显示第二区-复选框'].更新(非 已显示2)
        窗口['-第二区-'].更新(可见=已显示2)

窗口.关闭()

# %%
# 使用多个窗口

导入 快手

函 创建窗口1():
    布局 = [  [快手.标签('窗口 1')],
              [快手.标签('键入一些文字, 输出到窗口 2')],
              [快手.输入框(键='-输入-', 启用事件=真)],
              [快手.标签(大小=(25,1), 键='-输出-')],
              [快手.按钮('重新打开')],
              [快手.按钮('退出')]  ]
    返回 快手.窗口类('窗口标题', 布局, 定型=真)


函 创建窗口2():
    布局 = [  [快手.标签('窗口 2')],
              [快手.标签('键入一些文字, 输出到窗口 1')],
              [快手.输入框(键='-输入-', 启用事件=真)],
              [快手.标签(大小=(25,1), 键='-输出-')],
              [快手.按钮('退出')]  ]
    返回 快手.窗口类('窗口标题', 布局, 定型=真)


窗口1, 窗口2 = 创建窗口1(), 创建窗口2()

窗口2.移动(窗口1.当前位置()[0], 窗口1.当前位置()[1]+240)

只要 真:             # 事件循环
    窗口, 事件, 值 = 快手.读取所有窗口()

    如果 窗口 == 空:     # 如果所有窗口都关闭
        跳出
    如果 事件 == 空 或 事件 == '退出':
        窗口.关闭()
        如果 窗口 == 窗口2:       # 如果关闭窗口2, 则标记为已关闭
            窗口2 = 空
        或如 窗口 == 窗口1:       # 如果关闭窗口1, 则标记为已关闭
            窗口1 = 空
    或如 事件 == '重新打开':
        如果 非 窗口2:
            窗口2 = 创建窗口2()
            窗口2.移动(窗口1.当前位置()[0], 窗口1.当前位置()[1] + 240)
    或如 事件 == '-输入-':
        输出窗口 = 窗口2 如果 窗口 == 窗口1 否则 窗口1
        如果 输出窗口:           # 如果是有效窗口, 则输出到该窗口
            输出窗口['-输出-'].更新(值['-输入-'])
        否则:
            窗口['-输出-'].更新('另一窗口已关闭')

# %%
# 异步使用 - 轮询

导入 快手

快手.主题('深棕1')

布局 = [  [快手.标签('秒表', 大小=(20, 2), 对齐='居中')],
          [快手.标签(大小=(10, 2), 字体=('微软雅黑', 20), 对齐='居中', 键='-输出-')],
          [快手.标签(' ' * 5), 快手.按钮('开始/停止', 焦点=真), 快手.放弃按钮()]  ]

窗口 = 快手.窗口类('秒表计时器', 布局)

计时器运行, 计数器 = 真, 0

只要 真:                                 # 事件循环
    事件, 值 = 窗口.读取(超时=10)         # 尽可能使用较大的超时值
    如果 事件 在 (空, '放弃'):            # 如果用户关闭窗口
        跳出
    或如 事件 == '开始/停止':
        计时器运行 = 非 计时器运行
    如果 计时器运行:
        窗口['-输出-'].更新('{:02d}:{:02d}.{:02d}'.格式化((计数器 // 100) // 60, (计数器 // 100) % 60, 计数器 % 100))
        计数器 += 1
窗口.关闭()

# %%
# 模拟回调函数

导入 快手

快手.主题('淡蓝3')

# 回调函数
函 按钮1函数():
    打印('按钮 1 回调函数')

函 按钮2函数():
    打印('按钮 2 回调函数')

# 按钮映射到要调用的函数
派遣字典 = {'1':按钮1函数, '2':按钮2函数} # 使用简单的派遣字典存储事件和函数

布局 = [[快手.标签('请点击一个按钮', 大小适应文本=真)],
          [快手.按钮('1'), 快手.按钮('2'), 快手.按钮('3'), 快手.放弃按钮()]]

窗口 = 快手.窗口类('按钮回调函数示例', 布局)

# 事件循环. 读取按钮, 执行回调函数
只要 真:
    事件, 值 = 窗口.读取()
    如果 事件 在 ('放弃', 空):
        跳出
    如果 事件 在 派遣字典:
        要调用的函数 = 派遣字典[事件]   # 从派遣字典中获取函数
        要调用的函数()
    否则:
        打印('事件 {} 不在派遣字典中'.格式化(事件))

窗口.关闭()

快手.弹窗_确定('完成')

# %%
# 扫雷游戏样式的按钮网格
# 注意: 事件和键可以是任意类型, 不限于字符串

导入 快手
从 随机数 导入 随机整数

最大行数 = 最大列数 = 10
雷区 = [[随机整数(0,1) 取 j 于 范围(最大列数)] 取 i 于 范围(最大行数)]

布局 =  [[快手.按钮('?', 大小=(4, 2), 键=(i,j), 边距=(0,0)) 取 j 于 范围(最大列数)] 取 i 于 范围(最大行数)]

窗口 = 快手.窗口类('扫雷', 布局)

只要 真:
    事件, 值 = 窗口.读取()
    如果 事件 == 空:
        跳出
    # 窗口[(行, 列)].更新('新文本')   # 使用这种方式更改按钮文本
    # 对于此例, 按钮文本变为地雷的值, 颜色变为黑色
    窗口[事件].更新(雷区[事件[0]][事件[1]], 按钮颜色=('#FFFFFF','#000000'))  # 白色, 黑色
窗口.关闭()

# %%
# 定制进度条

导入 快手

布局 = [  [快手.标签('定制进度条')],
          [快手.进度条(1000, 方向='水平', 大小=(20, 20), 键='进度条')],
          [快手.取消按钮()]  ]

窗口 = 快手.窗口类('定制进度条', 布局)

取 i 于 范围(1000):
    事件, 值 = 窗口.读取(超时=0)
    如果 事件 == '取消' 或 事件 == 空:
        跳出
    窗口['进度条'].更新(i + 1)

窗口.关闭()

# %%
# 运行命令并在滚动窗口中显示输出

导入 快手
导入 子进程

函 执行命令子进程(命令, *参数):      
    试:      
        进程管道 = 子进程.开启管道类([命令, *参数], 壳=真, 标准输出=-1, 标准错误=-1)      
        输出, 错误 = 进程管道.通信()      
        如果 输出:      
            打印(输出.解码("utf-8"))      
        如果 错误:      
            打印(错误.解码("utf-8"))      
    捕:      
        无操作      


布局 = [      
    [快手.标签('脚本输出....', 大小=(40, 1))],      
    [快手.输出框(大小=(88, 20))],      
    [快手.按钮('脚本1'), 快手.按钮('脚本2'), 快手.按钮('退出')],      
    [快手.标签('手动输入命令', 大小=(15, 1)), 快手.输入框(焦点=真), 快手.按钮('运行', 绑定回车键=真)]      
      ]      

窗口 = 快手.窗口类('运行脚本', 布局)      

# ---===--- 循环: 接收用户输入, 据此调用脚本 --- #      

只要 真:      
    (事件, 值) = 窗口.读取()      
    如果 事件 == '退出'  或 事件 == 空:      
        跳出
    如果 事件 == '脚本1':      
        执行命令子进程('pip', 'list')      
    elif 事件 == '脚本2':      
        执行命令子进程('python', '--version')      
    elif 事件 == '运行':      
        执行命令子进程(值[0])      

窗口.关闭()

# %%
# 点击按钮运行程序

导入 快手
导入 子进程

CHROME = r"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe"  

布局 = [  [快手.标签('输入网址', 键='-文本-')],  
          [快手.输入框(键='-URL-')],  
          [快手.按钮('浏览'), 快手.按钮('退出')]  ]  

窗口 = 快手.窗口类('窗口标题', 布局)  

只要 真:              
    事件, 值 = 窗口.读取()  
    打印(事件, 值)  
    如果 事件 == 空 或 事件 == '退出':  
        跳出  
    如果 事件 == '浏览':  
        子进程.开启管道类([CHROME, 值['-URL-']], 壳=真, 标准输出=-1, 标准错误=-1)

窗口.关闭()

# %%
# 布局 - 元素块

导入 快手

元素块 = [
            [快手.标签('元素块第一行', 文本颜色='white', 背景颜色='blue')],      
            [快手.标签('元素块第二行', 文本颜色='white', 背景颜色='blue'), 快手.输入框('元素块输入 1')],      
            [快手.标签('元素块第三行', 文本颜色='white', 背景颜色='blue'), 快手.输入框('元素块输入 2')]
        ]

布局 = [
        [快手.列表框(值选项=('列表项 1', '列表项 2', '列表项 3'), 选择模式=快手.列表框_多选, 大小=(20,3)), 快手.列(元素块, 背景颜色='blue')],      
        [快手.输入框('最后的输入')],      
        [快手.确定按钮()]
       ]      

# 显示窗口并获取值

事件, 值 = 快手.窗口类('带元素块的窗口', 布局).读取(关闭=真)  # 缩写形式

快手.弹窗(事件, 值, 行宽=200)

# %%
# 模拟触摸屏密码器

导入 快手

布局 = [
        [快手.标签('请输入密码')],
        [快手.输入框(大小=(10, 1), 对齐='右', 键='输入')],
        [快手.按钮('1'), 快手.按钮('2'), 快手.按钮('3')],
        [快手.按钮('4'), 快手.按钮('5'), 快手.按钮('6')],
        [快手.按钮('7'), 快手.按钮('8'), 快手.按钮('9')],
        [快手.按钮('提交'), 快手.按钮('0'), 快手.按钮('清空')],
        [快手.标签(大小=(15, 1), 字体=('Helvetica', 18), 文本颜色='red', 键='输出')]
      ]

窗口 = 快手.窗口类('小键盘', 布局, 默认按钮元素大小=(5,2), 按钮适应文本=假)

所按的键 = ''

只要 真:
    事件, 值 = 窗口.读取()
    如果 事件 == 空:
        跳出
    如果 事件 == '清空':
        所按的键 = ''
    或如 事件 在 '1234567890':
        所按的键 = 值['输入']
        所按的键 += 事件
    或如 事件 == '提交':
        所按的键 = 值['输入']
        窗口['输出'].更新(所按的键)

    窗口['输入'].更新(所按的键)  

窗口.关闭()

# %%
# 密码保护

导入 快手
导入 哈希库      

# 使用此 GUI 获取密码的哈希码
函 哈希生成器GUI():      
    布局 = [
            [快手.标签('密码哈希值生成器', 大小=(30,1), 字体='微软雅黑')],      
            [快手.标签('密码'), 快手.输入框(焦点=真, 键='密码')],      
            [快手.标签('SHA 哈希值'), 快手.输入框('', 大小=(40,1), 键='hash')],      
           ]      

    窗口 = 快手.窗口类('SHA 生成器', 布局, 大小适应文本=假, 默认元素大小=(10,1),      
                        文本对齐='右', 返回键盘事件=真, 任意地方抓取=假)

    只要 真:      
        事件, 值 = 窗口.读取()      
        如果 事件 ==  空:
            退出(69)      

        密码 = 值['密码']      
        试:      
            密码utf = 密码.编码('utf-8')      
            sha1hash = 哈希库.sha1()      
            sha1hash.更新(密码utf)      
            密码哈希值 = sha1hash.十六进制摘要()      
            窗口['hash'].更新(密码哈希值)      
        捕:      
            无操作      

# 通过比较哈希值判断输入的密码是否匹配
函 密码匹配(密码, hash):      
    密码utf = 密码.编码('utf-8')      
    sha1hash = 哈希库.sha1()      
    sha1hash.更新(密码utf)      
    密码哈希值 = sha1hash.十六进制摘要()      
    如果 密码哈希值 == hash:
        返回 真      
    否则:      
        返回 假      

登录密码哈希值 = 'd8873bb3935b9a689fa86c7b9a6a6f1b531d7863'      
密码 = 快手.弹窗_获取文本('密码', 密码字符='*')      
如果 密码 == 'gui':               
    哈希生成器GUI()                
    退出(69)                         
如果 密码匹配(密码, 登录密码哈希值):      
    打印('登录成功!')      
否则:      
    打印('登录失败!!')     

# %%
# 无标题桌面浮动窗口

导入 快手

快手.更改外观('黑色')
布局 = [ 
            [快手.标签('')],
            [快手.标签('CPU 10%', 大小=(8, 2), 字体=('微软雅黑', 20), 对齐='居中', 键='文本')],
            [快手.退出按钮(按钮颜色=('#FFFFFF', '#FF4500'), 边距=((15, 0), 0)),
                快手.旋钮控件([x + 1 取 x 于 范围(10)], 1, 启用事件=真, 键='旋钮')]
        ]

窗口 = 快手.窗口类('CPU 利用率', 布局, 无标题栏=真, 按钮适应文本=假, 保持置顶=真, 任意地方抓取=真)

只要 真:
    事件, 值 = 窗口.读取()

    如果 事件 == 空 或 事件 == '退出':
        跳出
    试:
        cpu利用率 = 整数(值['旋钮'])
    捕:
        cpu利用率 = 1

    窗口['文本'].更新(f'CPU {cpu利用率:02.0f}%')

窗口.关闭()

# %%
# 使用图形元素

导入 数学    
导入 快手 

布局 = [ [快手.绘图区(画布大小=(400, 400), 左下=(-105,-105), 右上=(105,105), 背景颜色='white', 键='图形', 提示='酷图!')] ]    

窗口 = 快手.窗口类('正弦函数图', 布局, 任意地方抓取=真).定型()    
图形 = 窗口['图形']  

# 画坐标轴
图形.画线((-100,0), (100,0))    
图形.画线((0,-100), (0,100))    

取 x 于 范围(-100, 101, 20):    
    图形.画线((x,-3), (x,3))    
    if x != 0:    
        图形.画文字( x, (x,-10), 颜色='green')    

取 y 于 范围(-100, 101, 20):    
    图形.画线((-3,y), (3,y))    
    if y != 0:    
        图形.画文字( y, (-10,y), 颜色='blue')    

# 画图
取 x 于 范围(-100,100):    
    y = 数学.sin(x/20)*50    
    图形.画圆((x,y), 1, 线颜色='red', 填充颜色='red')    

事件, 值 = 窗口.读取()

# %%
# 选项卡

导入 快手

选项卡1布局 =  [
                [快手.标签('这里在选项卡 1 中')]
              ]    

选项卡2布局 = [
                [快手.标签('这里在选项卡 2 中')],    
                [快手.输入框(键='输入')]
             ]    

布局 = [  [快手.选项卡组([[快手.选项卡('选项卡 1', 选项卡1布局, 提示='嘿嘿'), 快手.选项卡('选项卡 2', 选项卡2布局)]], 提示='呵呵')],    
          [快手.按钮('读取')]  ]    

窗口 = 快手.窗口类('带选项卡的窗口', 布局, 默认元素大小=(12,1))    

只要 真:    
    事件, 值 = 窗口.读取()    
    打印(事件, 值)    
    如果 事件 == 空:
        跳出

窗口.关闭()

# %%
# 创建 Windows .exe 文件

# pyinstaller -wF my_program.py

# %%
导入 快手

布局 = [  [快手.标签('5 - 1 = ')],      
          [快手.单选按钮('1', '答案', 大小=(5,1)), 快手.单选按钮('2', '答案', 大小=(5,1)), 
            快手.单选按钮('3', '答案', 大小=(5,1)), 快手.单选按钮('4', '答案', 大小=(5,1))],      
          [快手.按钮('重做'), 快手.按钮('提交')]  ]      

窗口 = 快手.窗口类('选择题', 布局)

只要 真:                             # 事件循环
    事件, 值 = 窗口.读取() 
    打印(事件, 值)       
    如果 事件 == 空 或 事件 == '提交':  # 退出窗口事件
        跳出      

窗口.关闭()
# %%
